Gabriel Chaix 50% | Elsa Chevrot 50%¶
TD 8/9 : Analyse des données¶
Demandes de valeurs foncières¶
Dataset OpenData :¶
Il s'agit des transactions immobilières intervenues au cours des cinq dernières années sur le territoire métropolitain et les DOM-TOM, à l’exception de l’Alsace, de la Moselle et de Mayotte. Les données contenues sont issues des actes notariés et des informations cadastrales.
Mini rapport :¶
blablablabalbalb¶
abla lbalba lb albalblbl abllblab lblbl
Librairies¶
Install
%load_ext pretty_jupyter
%load_ext jinja2
The pretty_jupyter extension is already loaded. To reload it, use: %reload_ext pretty_jupyter The jinja2 module is not an IPython extension.
# install calmap pour colab
#! pip install calmap
#mettre à jour plotly pour colab
#!pip install plotly==4.5.2
#!pip install plotly
#!pip install geopandas
#!pip install jinja2
Imports
# librairies essentielles
import json
import requests
import random
from urllib.request import urlopen
from collections import Counter
# analyse et stockage
import numpy as np
import pandas as pd
# visualisation
import warnings
warnings.filterwarnings('ignore')
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import geopandas as gpd
colors1 = ['#DAF7A6', '#FFC300', '#FF5733', '#C70039', '#900C3F', '#581845']
colors2 = ["#e60049", "#0bb4ff", "#50e991", "#e6d800", "#9b19f5", "#ffa300", "#dc0ab4", "#b3d4ff", "#00bfa0"]
colors3 = ["#1984c5", "#22a7f0", "#63bff0", "#a7d5ed", "#e2e2e2", "#e1a692", "#de6e56", "#e14b31", "#c23728"]
I ] Chargement¶
df = pd.read_csv('https://static.data.gouv.fr/resources/demandes-de-valeurs-foncieres/20230405-160733/valeursfoncieres-2022.txt', sep = '|')
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 3803885 entries, 0 to 3803884 Data columns (total 43 columns): # Column Dtype --- ------ ----- 0 Identifiant de document float64 1 Reference document float64 2 1 Articles CGI float64 3 2 Articles CGI float64 4 3 Articles CGI float64 5 4 Articles CGI float64 6 5 Articles CGI float64 7 No disposition int64 8 Date mutation object 9 Nature mutation object 10 Valeur fonciere object 11 No voie float64 12 B/T/Q object 13 Type de voie object 14 Code voie object 15 Voie object 16 Code postal float64 17 Commune object 18 Code departement object 19 Code commune int64 20 Prefixe de section float64 21 Section object 22 No plan int64 23 No Volume object 24 1er lot object 25 Surface Carrez du 1er lot object 26 2eme lot object 27 Surface Carrez du 2eme lot object 28 3eme lot object 29 Surface Carrez du 3eme lot object 30 4eme lot float64 31 Surface Carrez du 4eme lot object 32 5eme lot float64 33 Surface Carrez du 5eme lot object 34 Nombre de lots int64 35 Code type local float64 36 Type local object 37 Identifiant local float64 38 Surface reelle bati float64 39 Nombre pieces principales float64 40 Nature culture object 41 Nature culture speciale object 42 Surface terrain float64 dtypes: float64(17), int64(4), object(22) memory usage: 1.2+ GB
# formatage des noms des colonnes
df = df.rename(columns=lambda x: x.replace(' ', '_').lower())
II ] Nettoyage¶
#Vérifier les parts des données manquantes dans la base brutes
df.isnull().sum()/len(df)*100
identifiant_de_document 100.000000 reference_document 100.000000 1_articles_cgi 100.000000 2_articles_cgi 100.000000 3_articles_cgi 100.000000 4_articles_cgi 100.000000 5_articles_cgi 100.000000 no_disposition 0.000000 date_mutation 0.000000 nature_mutation 0.000000 valeur_fonciere 0.649888 no_voie 34.733621 b/t/q 95.374019 type_de_voie 36.984294 code_voie 1.026398 voie 1.029290 code_postal 1.029816 commune 0.000000 code_departement 0.000000 code_commune 0.000000 prefixe_de_section 95.824295 section 0.004075 no_plan 0.000000 no_volume 99.765792 1er_lot 66.631142 surface_carrez_du_1er_lot 90.332568 2eme_lot 89.535278 surface_carrez_du_2eme_lot 96.741752 3eme_lot 98.134670 surface_carrez_du_3eme_lot 99.635662 4eme_lot 99.402611 surface_carrez_du_4eme_lot 99.911880 5eme_lot 99.744130 surface_carrez_du_5eme_lot 99.967481 nombre_de_lots 0.000000 code_type_local 39.918478 type_local 39.918478 identifiant_local 100.000000 surface_reelle_bati 39.973396 nombre_pieces_principales 39.973396 nature_culture 33.830912 nature_culture_speciale 95.934262 surface_terrain 33.830912 dtype: float64
# suppression des attributs non nécessaire
df = df.drop(['identifiant_de_document',
'reference_document',
'1_articles_cgi',
'2_articles_cgi',
'3_articles_cgi',
'4_articles_cgi',
'5_articles_cgi',
'prefixe_de_section',
'no_volume',
'3eme_lot',
'4eme_lot',
'5eme_lot',
'identifiant_local',
'nature_culture_speciale',
],axis= 1)
# suppression des doubles
df = df.drop_duplicates()
# suppression des ligne null
df = df.dropna(how="all")
# correction des types de données
df['date_mutation'] = pd.to_datetime(df['date_mutation'])
df['nature_mutation'] = df['nature_mutation'].astype('category')
df['valeur_fonciere'] = df['valeur_fonciere'].str.replace(',', '.').astype('float')
df['no_voie'] = df['no_voie'].astype('Int32')
df['b/t/q'] = df['b/t/q'].astype('category')
df['code_postal'] = df['code_postal'].astype('Int32')
df['code_commune'] = df['code_commune'].astype('int32')
df['no_plan'] = df['no_plan'].astype('int32')
df['1er_lot'] = df['1er_lot'].astype('category')
df['2eme_lot'] = df['2eme_lot'].astype('category')
df['surface_carrez_du_1er_lot'] = df['surface_carrez_du_1er_lot'].str.replace(',', '.').astype('float')
df['surface_carrez_du_2eme_lot'] = df['surface_carrez_du_2eme_lot'].str.replace(',', '.').astype('float')
df['surface_carrez_du_3eme_lot'] = df['surface_carrez_du_3eme_lot'].str.replace(',', '.').astype('float')
df['surface_carrez_du_4eme_lot'] = df['surface_carrez_du_4eme_lot'].str.replace(',', '.').astype('float')
df['surface_carrez_du_5eme_lot'] = df['surface_carrez_du_5eme_lot'].str.replace(',', '.').astype('float')
df['nombre_de_lots'] = df['nombre_de_lots'].astype('int32')
df['code_type_local'] = df['code_type_local'].astype('Int32')
df['type_local'] = df['type_local'].astype('category')
df['surface_reelle_bati'] = df['surface_reelle_bati'].astype('float')
df['nombre_pieces_principales'] = df['nombre_pieces_principales'].astype('Int32')
df['nature_culture'] = df['nature_culture'].astype('category')
df['surface_terrain'] = df['surface_terrain'].astype('float')
#suppression des valeur_fonciere null
df = df[df['valeur_fonciere'] > 0]
df['surface_carrez_du_1er_lot'].fillna(0, inplace=True)
df['surface_carrez_du_2eme_lot'].fillna(0, inplace=True)
df['surface_carrez_du_3eme_lot'].fillna(0, inplace=True)
df['surface_carrez_du_4eme_lot'].fillna(0, inplace=True)
df['surface_carrez_du_5eme_lot'].fillna(0, inplace=True)
df.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 3509650 entries, 0 to 3803884 Data columns (total 29 columns): # Column Dtype --- ------ ----- 0 no_disposition int64 1 date_mutation datetime64[ns] 2 nature_mutation category 3 valeur_fonciere float64 4 no_voie Int32 5 b/t/q category 6 type_de_voie object 7 code_voie object 8 voie object 9 code_postal Int32 10 commune object 11 code_departement object 12 code_commune int32 13 section object 14 no_plan int32 15 1er_lot category 16 surface_carrez_du_1er_lot float64 17 2eme_lot category 18 surface_carrez_du_2eme_lot float64 19 surface_carrez_du_3eme_lot float64 20 surface_carrez_du_4eme_lot float64 21 surface_carrez_du_5eme_lot float64 22 nombre_de_lots int32 23 code_type_local Int32 24 type_local category 25 surface_reelle_bati float64 26 nombre_pieces_principales Int32 27 nature_culture category 28 surface_terrain float64 dtypes: Int32(4), category(6), datetime64[ns](1), float64(8), int32(3), int64(1), object(6) memory usage: 589.6+ MB
df.head()
| no_disposition | date_mutation | nature_mutation | valeur_fonciere | no_voie | b/t/q | type_de_voie | code_voie | voie | code_postal | ... | surface_carrez_du_3eme_lot | surface_carrez_du_4eme_lot | surface_carrez_du_5eme_lot | nombre_de_lots | code_type_local | type_local | surface_reelle_bati | nombre_pieces_principales | nature_culture | surface_terrain | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2022-03-01 | Vente | 55000.0 | 13 | NaN | RUE | 2280 | DE LA LIBERTE | 1000 | ... | 0.0 | 0.0 | 0.0 | 1 | 2 | Appartement | 24.0 | 1 | NaN | NaN |
| 1 | 1 | 2022-03-01 | Vente | 143000.0 | <NA> | NaN | NaN | B010 | CHAMP COCHET | 1480 | ... | 0.0 | 0.0 | 0.0 | 0 | <NA> | NaN | NaN | <NA> | S | 84.0 |
| 2 | 1 | 2022-03-01 | Vente | 143000.0 | <NA> | NaN | NaN | B010 | CHAMP COCHET | 1480 | ... | 0.0 | 0.0 | 0.0 | 0 | <NA> | NaN | NaN | <NA> | S | 88.0 |
| 3 | 1 | 2022-03-01 | Vente | 143000.0 | 98 | NaN | RTE | 0055 | DE LA DOMBES | 1480 | ... | 0.0 | 0.0 | 0.0 | 1 | 2 | Appartement | 140.0 | 3 | NaN | NaN |
| 4 | 1 | 2022-04-01 | Vente | 300.0 | <NA> | NaN | NaN | B031 | AUX PIERRES | 1480 | ... | 0.0 | 0.0 | 0.0 | 0 | <NA> | NaN | NaN | <NA> | T | 510.0 |
5 rows × 29 columns
III ] Interprétations¶
Générales¶
- Quelle est la part de maison, d'appartement, ect.. dans le dataset?
# Quelle est la part de maison, d'appartement, ect.. dans le dataset?
types = df['type_local'].value_counts(dropna = False, normalize = True).head()
plt.figure(figsize=(8,8))
plt.pie(types.values, labels=types.index, colors = colors2, startangle=65)
plt.title(label= 'Parts des types de biens')
plt.legend(loc = 4)
<matplotlib.legend.Legend at 0x7fe89424f820>
- Prix au mètre carré en fonction du type de local
# Prix au mètre carré en fonction du type de local
pm2 = df[(df['nombre_de_lots']<6) & ((df['surface_carrez_du_1er_lot'] + df['surface_carrez_du_2eme_lot'] + df['surface_carrez_du_3eme_lot'] + df['surface_carrez_du_4eme_lot'] + df['surface_carrez_du_5eme_lot']) > 0)]
pm2['surface_totale'] = pm2['surface_carrez_du_1er_lot'] + pm2['surface_carrez_du_2eme_lot'] + pm2['surface_carrez_du_3eme_lot'] + pm2['surface_carrez_du_4eme_lot'] + pm2['surface_carrez_du_5eme_lot']
pm2['prix_m2'] = pm2['valeur_fonciere'] / pm2['surface_totale']
sns.set(rc={'figure.figsize':(40,30)})
sns.color_palette()
sns.catplot(x="type_local", y="prix_m2", jitter=True, data=pm2, kind="strip", height=8, aspect=1.5, palette="Set2")
#sns.stripplot(pm2['type_local'],pm2['prix_m2'],jitter=True)
#pm2.loc[:,['type_local','prix_m2']].plot(kind='scatter',x='type_local',y='prix_m2')
<seaborn.axisgrid.FacetGrid at 0x7fe9517629a0>
- Comparaison de plusieurs types de local
prixlocal = df.loc[df['type_local'].notna() & df['surface_terrain'].notna() & df['surface_terrain'] >= 1 & df['valeur_fonciere'].notna(),("surface_terrain","valeur_fonciere","type_local")]
prixlocal['prix_m2_sur_le_terrain'] = prixlocal['valeur_fonciere']/prixlocal['surface_terrain']
prixlocal['valeur_fonciere'] = prixlocal['valeur_fonciere']/1000
prixlocal.groupby(['type_local']).mean().plot.bar(title = 'Comparaison de différents types de local',figsize=(20,5))
<AxesSubplot:title={'center':'Comparaison de différents types de local'}, xlabel='type_local'>
- Surface du terrain par département
fig = plt.figure(4,figsize = (30,5))
axis = fig.add_subplot(1, 1, 1)
axis.set_title('Surface du terrain en fonction du département')
axis.set_xlabel("Département")
axis.set_ylabel("Surface du terrain")
chmp = df.loc[df["code_departement"].notna(),("surface_terrain","code_departement")]
gb = chmp.groupby("code_departement",dropna= False).mean()['surface_terrain'].reset_index()
axis.bar(gb["code_departement"].astype(str), gb["surface_terrain"])
plt.xticks(rotation=90)
fig.show()
- Quelle est la valeur foncière moyenne par département en 2022 (bar plot) ?
#Quelle est la valeur foncière moyenne par departement en utilisant un bar plot ?
grouped_vf_dept = df.groupby('code_departement')['valeur_fonciere'].mean().reset_index()
grouped_vf_dept['code_departement'] = grouped_vf_dept['code_departement'].astype('string')
fig = px.bar(grouped_vf_dept, y='valeur_fonciere',
x='code_departement',
text_auto='.2s')
fig.update_layout(title="Valeur foncière moyenne par département",
yaxis_title='Valeur foncière moyenne (€)',
xaxis_title='Département');
%%jmd
[//]: # (-.-|m { input: true, output_error: false, input_fold: hide })
{#fig.to_html(include_plotlyjs=False,full_html=False)#}
- Quelle est la valeur foncière moyenne par département en 2022 (geojson et choropleth) ?
#Quelle est la valeur foncière moyenne par département en 2022 (geojson et choropleth) ?
geojson_url = "https://france-geojson.gregoiredavid.fr/repo/departements.geojson"
geojson_data = requests.get(geojson_url).json()
fig = px.choropleth(grouped_vf_dept,
geojson=geojson_data,
locations='code_departement',
color='valeur_fonciere',
color_continuous_scale='pinkyl',
featureidkey='properties.code',
projection="mercator",
title='Valeur foncière moyenne par départements')
fig.update_geos(fitbounds="locations", visible=False)
fig.update_layout(height=600, width=800);
%%jmd
[//]: # (-.-|m { input: true, output_error: false, input_fold: hide })
{ fig.to_html(include_plotlyjs=False, full_html=False) }
- Quelle est la valeur foncière moyenne par pays, par département et par commune (treemap) ?
# Quelle est la valeur foncière moyenne par pays, par département (treemap) ?
df_avg = df.groupby(['code_departement'])['valeur_fonciere'].mean().reset_index()
fig = px.treemap(df_avg,
path=[px.Constant("France"),'code_departement'],
values='valeur_fonciere',
color='valeur_fonciere')
fig.update_layout(title='Carte proportionelle de la valeur foncière moyenne');
#fig.show()
%%jmd
[//]: # (-.-|m { input: true, output_error: false, input_fold: hide })
{ fig.to_html(include_plotlyjs=False, full_html=False) }
On s'aperçoit que la valeur foncière est fortement correlée avec la position géographique.
- Quelle est la surface réelle bâtie moyenne par département?
# Quelle est la surface réelle bâtie moyenne par département?
grouped_srb_dept = df[df['surface_reelle_bati'] > 0]
grouped_srb_dept = grouped_srb_dept.groupby('code_departement')['surface_reelle_bati'].mean().reset_index()
grouped_srb_dept['code_departement'] = grouped_srb_dept['code_departement'].astype('string')
fig = px.bar(grouped_srb_dept, y='surface_reelle_bati',
x='code_departement',
text_auto='.2s')
fig.update_layout(title="Surface réelle bâtie moyenne par departement",
yaxis_title='Valeur foncière moyenne (€)',
xaxis_title='Département');
#fig.show()
%%jmd
[//]: # (-.-|m { input: true, output_error: false, input_fold: hide })
{ fig.to_html(include_plotlyjs=False, full_html=False) }
- Quels sont les départements les plus chers pour l'immobilier en 2022 ?
# Quels sont les départements les plus chers pour l'immobilier en 2022 ?
grouped_vf_dept_top10 = grouped_vf_dept.sort_values('valeur_fonciere', ascending=False).head(10)
fig = px.bar(grouped_vf_dept_top10, x='valeur_fonciere', y='code_departement', orientation='h')
fig.update_layout(title='Les départements les plus chers pour l\'immobilier en 2022',
xaxis_title='Valeur foncière moyenne (€)',
yaxis_title='Département');
#fig.show()
%%jmd
[//]: # (-.-|m { input: true, output_error: false, input_fold: hide })
{ fig.to_html(include_plotlyjs=False, full_html=False) }
- Valeur foncière moyenne par jour en 2022
# Valeur foncière moyenne par jour en 2022
filtered_df = df[df['valeur_fonciere'] <= 4000000]
daily_means = filtered_df.groupby(filtered_df['date_mutation'].dt.date)['valeur_fonciere'].mean()
plt.scatter(daily_means.index, daily_means.values, c='red', label='Prix moyen')
avg_value = df['valeur_fonciere'].mean()
plt.axhline(y=avg_value, color='green', linestyle='solid', label='Valeur foncière moyenne sur 2022')
tick_dates = pd.date_range(start='2022-01-01', end='2022-12-31', freq='2M')
tick_labels = [date.strftime('%Y-%m') for date in tick_dates]
plt.xticks(ticks=tick_dates, labels = tick_labels, rotation=80)
plt.title('Valeur foncière moyenne par jour en 2022')
plt.xlabel("Date")
plt.ylabel("Valeur foncière moyenne")
plt.legend()
plt.show()
- Quelle est la valeur foncière moyenne à Paris en 2022 ?
#Quelle est la valeur foncière moyenne par commune dans le 75 en utilisant geojson et choropleth ?
geojson_url = "https://france-geojson.gregoiredavid.fr/repo/departements/75-paris/communes-75-paris.geojson"
geojson_data = requests.get(geojson_url).json()
vf_com_paris = df[(df['code_departement']==75) & df['valeur_fonciere'] > 0]
vf_com_paris = vf_com_paris.groupby('code_commune')['valeur_fonciere'].mean().reset_index()
vf_com_paris['code_commune'] = '75'+vf_com_paris['code_commune'].astype(str)
fig = px.choropleth(vf_com_paris,
geojson=geojson_data,
locations='code_commune',
color='valeur_fonciere',
color_continuous_scale='Reds',
featureidkey='properties.code',
projection="mercator",
title="Valeur fonciére moyenne en €")
fig.update_geos(fitbounds="locations", visible=False)
fig.update_layout(height=600,
width=800);
#fig.show()
%%jmd
[//]: # (-.-|m { input: true, output_error: false, input_fold: hide })
{ fig.to_html(include_plotlyjs=False, full_html=False) }
- Quel est le prix moyen du mètre carré pour les appartements à Paris en 2022 ?
#Quelle est le prix moyen d'un mètre carré dans les communes du 75 en utilisant geojson et choropleth ?
geojson_url = "https://france-geojson.gregoiredavid.fr/repo/departements/75-paris/communes-75-paris.geojson"
geojson_data = requests.get(geojson_url).json()
vf_com_paris = df[(df['code_departement'] == 75) & (df['nombre_de_lots']<6) & ((df['surface_carrez_du_1er_lot'] + df['surface_carrez_du_2eme_lot'] + df['surface_carrez_du_3eme_lot'] + df['surface_carrez_du_4eme_lot'] + df['surface_carrez_du_5eme_lot']) > 0)]
vf_com_paris['surface_totale'] = vf_com_paris['surface_carrez_du_1er_lot'] + vf_com_paris['surface_carrez_du_2eme_lot'] + vf_com_paris['surface_carrez_du_3eme_lot'] + vf_com_paris['surface_carrez_du_4eme_lot'] + vf_com_paris['surface_carrez_du_5eme_lot']
vf_com_paris['prix_m2'] = vf_com_paris['valeur_fonciere'] / vf_com_paris['surface_totale']
vf_com_paris = vf_com_paris.groupby('code_commune')['prix_m2'].mean().reset_index()
vf_com_paris['code_commune'] = '75'+vf_com_paris['code_commune'].astype(str)
fig = px.choropleth(vf_com_paris,
geojson=geojson_data,
locations='code_commune',
color='prix_m2',
color_continuous_scale='Reds',
featureidkey='properties.code',
projection="mercator",
title="Prix moyen d'un mètre carré en €")
fig.update_geos(fitbounds="locations", visible=False)
fig.update_layout(height=600,
width=800);
#fig.show()
%%jmd
[//]: # (-.-|m { input: true, output_error: false, input_fold: hide })
{ fig.to_html(include_plotlyjs=False, full_html=False) }
- Nombre de bien vendu dans les 20 villes
#Nombre de bien vendu dans les 20 villes
plt.rcParams['figure.figsize'] = [18, 5]
plt.rcParams['figure.dpi'] = 150
vente_ville = df.groupby(['commune']).size().sort_values(ascending = False).head(20)
x = vente_ville.index
y = vente_ville.tolist()
plt.scatter(x, y, color='#119670', marker='o', label = 'Nombre de biens vendus')
plt.title('Nombre de biens vendus par ville', fontsize = 13)
plt.xticks(rotation=60)
plt.xlabel("Ville", fontsize = 12)
plt.ylabel("Nombre de biens vendus", fontsize = 12)
plt.legend(loc = 'upper right')
plt.grid(True)
plt.show()
Lyon¶
- Valeur foncière moyenne par arrondissement de Lyon en 2022
#Valeur foncière moyenne par arrondissement de Lyon en 2022
lyon = df.loc[(df['commune'].str.contains("LYON")) & (df['commune'].str.contains("EME"))]
arrondissement_lyon = lyon.groupby(['commune']).mean().sort_values(['valeur_fonciere'])
x = arrondissement_lyon.index
y = arrondissement_lyon['valeur_fonciere']
arrondissement_lyon.head()
| no_disposition | valeur_fonciere | no_voie | code_postal | code_commune | no_plan | surface_carrez_du_1er_lot | surface_carrez_du_2eme_lot | surface_carrez_du_3eme_lot | surface_carrez_du_4eme_lot | surface_carrez_du_5eme_lot | nombre_de_lots | code_type_local | surface_reelle_bati | nombre_pieces_principales | surface_terrain | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| commune | ||||||||||||||||
| LYON 5EME | 1.004388 | 3.994591e+05 | 75.831055 | 69005.0 | 385.0 | 65.937591 | 19.938532 | 14.818713 | 0.382535 | 0.247450 | 0.000000 | 1.440761 | 2.592653 | 32.749325 | 1.309562 | 544.486726 |
| LYON 8EME | 1.002674 | 4.306062e+05 | 114.843302 | 69008.0 | 388.0 | 95.938235 | 29.448888 | 9.278094 | 0.381725 | 0.076824 | 0.000000 | 1.259626 | 2.613522 | 31.058805 | 1.145597 | 395.252427 |
| LYON 2EME | 1.034025 | 7.951936e+05 | 470.339226 | 69002.0 | 382.0 | 75.083817 | 31.912398 | 11.221286 | 2.977950 | 0.412515 | 0.581220 | 1.497925 | 2.587056 | 49.271650 | 1.314494 | 286.984615 |
| LYON 4EME | 1.021396 | 1.108314e+06 | 34.029296 | 69004.0 | 384.0 | 82.764640 | 22.410034 | 11.182523 | 1.084077 | 0.211948 | 0.000000 | 1.453829 | 2.598499 | 33.168230 | 1.225141 | 458.433333 |
| LYON 7EME | 1.006498 | 1.184941e+06 | 60.617319 | 69007.0 | 387.0 | 91.363890 | 25.497069 | 7.844611 | 0.545372 | 0.178652 | 0.006011 | 1.277327 | 2.615996 | 45.810305 | 1.099974 | 582.378788 |
#Valeur foncière moyenne par arrondissement de Lyon en 2022
plt.figure(1, figsize=(10, 6))
plt.plot(x, y, color='purple', marker='o', label='Prix moyen')
plt.title('Valeur fonciere moyenne par arrondissement de Lyon en 2021')
plt.xticks(rotation=80)
plt.xlabel("Arrondissements de Lyon")
plt.ylabel("Valeur fonciere moyenne")
plt.legend(loc = 'upper left')
plt.grid(True)
plt.show()
- Nombre de biens vendus par arrondissement de Lyon
# Nombre de biens vendus par arrondissement de Lyon
arrondissement_lyon = lyon.groupby(['commune']).size()
x = arrondissement_lyon.index.tolist()
y = arrondissement_lyon.tolist()
plt.figure(1, figsize=(10, 6))
plt.pie(y, labels = x, autopct = '%.2f')
plt.title("Pars de biens vendus par arrondissement à Lyon")
# Ajout d'un cercle au centre
my_circle=plt.Circle( (0,0), 0.7, color='white')
p=plt.gcf()
p.gca().add_artist(my_circle)
plt.show()
Relation diverse¶
- Nature des cultures en France en 2022
# Nature des cultures en France en 2022
plt.figure(figsize=(8,8))
plt.title('Nature des cultures françaises en 2022')
sns.set(rc={'figure.figsize':(3,9)})
sns.countplot(y='nature_culture', data=df)
<AxesSubplot:title={'center':'Nature des cultures françaises en 2022'}, xlabel='count', ylabel='nature_culture'>
- Relation entre valeur foncière et nature de mutation
# Relation entre valeur foncière et nature de mutation
df_ve = df[df['nature_mutation']=='Vente'].sort_values(by='valeur_fonciere', ascending=False)
se_vente_commune = df_ve.commune.value_counts()
plt.figure(figsize=(10,5))
df_best_city = df_ve[df_ve['commune'].isin(se_vente_commune.head(10).index)]
df_best_city = df_best_city[df_best_city['valeur_fonciere'] < df_best_city['valeur_fonciere'].quantile(.95)]
df_best_city = df_best_city[df_best_city['valeur_fonciere'] > df_best_city['valeur_fonciere'].quantile(.05)]
order=df_best_city['valeur_fonciere'].groupby(df_best_city.commune).median().sort_values(ascending=False)
plt.figure(figsize=(20,10))
ax = sns.boxplot(x=df_best_city.commune, y=df_best_city['valeur_fonciere'], order=order.index)
ax.set_title('Relation entre la commune et la valeur foncière')
ax.set_xlabel('Commune')
ax.set_ylabel('Valeur foncière')
Text(0, 0.5, 'Valeur foncière')
<Figure size 1500x750 with 0 Axes>
- Relation entre nombre de pièce principale et nature de mutation
# Relation entre nombre de pièce principale et nature de mutation
df_ve = df[df['nature_mutation']=='Vente'].sort_values(by='valeur_fonciere', ascending=False)
se_vente_nombre_pieces_principales = df_ve.nombre_pieces_principales.value_counts()
plt.figure(figsize=(10,5))
df_best_city = df_ve[df_ve['nombre_pieces_principales'].isin(se_vente_nombre_pieces_principales.head(10).index)]
df_best_city = df_best_city[df_best_city['valeur_fonciere'] < df_best_city['valeur_fonciere'].quantile(.95)]
df_best_city = df_best_city[df_best_city['valeur_fonciere'] > df_best_city['valeur_fonciere'].quantile(.05)]
order=df_best_city['valeur_fonciere'].groupby(df_best_city.nombre_pieces_principales).median().sort_values(ascending=False)
plt.figure(figsize=(20,10))
ax = sns.boxplot(x=df_best_city.nombre_pieces_principales, y=df_best_city['valeur_fonciere'], order=order.index)
ax.set_title('Relation entre le nombre pièce principale et la valeur foncière')
ax.set_xlabel('nombre_pieces_principales')
ax.set_ylabel('Valeur foncière')
Text(0, 0.5, 'Valeur foncière')
<Figure size 1500x750 with 0 Axes>
- Prix au m² selon le type de local ?
# Prix au mètre carré en fonction du type de local
pm2 = df[(df['nombre_de_lots']<6) & ((df['surface_carrez_du_1er_lot'] + df['surface_carrez_du_2eme_lot'] + df['surface_carrez_du_3eme_lot'] + df['surface_carrez_du_4eme_lot'] + df['surface_carrez_du_5eme_lot']) > 0)]
pm2['surface_totale'] = pm2['surface_carrez_du_1er_lot'] + pm2['surface_carrez_du_2eme_lot'] + pm2['surface_carrez_du_3eme_lot'] + pm2['surface_carrez_du_4eme_lot'] + pm2['surface_carrez_du_5eme_lot']
pm2['prix_m2'] = pm2['valeur_fonciere'] / pm2['surface_totale']
sns.set(rc={'figure.figsize':(40,30)})
sns.color_palette()
sns.catplot(x="type_local", y="prix_m2", jitter=True, data=pm2, kind="strip", height=8, aspect=1.5, palette="Set2")
<seaborn.axisgrid.FacetGrid at 0x7fe8a3fa4160>
- Prix au m² selon le nombre de pièce principale
# Prix au mètre carré en fonction du nombre de pièce principale
pm2 = df[(df['nombre_de_lots']<6) & ((df['surface_carrez_du_1er_lot'] + df['surface_carrez_du_2eme_lot'] + df['surface_carrez_du_3eme_lot'] + df['surface_carrez_du_4eme_lot'] + df['surface_carrez_du_5eme_lot']) > 0)]
pm2['surface_totale'] = pm2['surface_carrez_du_1er_lot'] + pm2['surface_carrez_du_2eme_lot'] + pm2['surface_carrez_du_3eme_lot'] + pm2['surface_carrez_du_4eme_lot'] + pm2['surface_carrez_du_5eme_lot']
pm2['prix_m2'] = pm2['valeur_fonciere'] / pm2['surface_totale']
pm2['nombre_pieces_principales'] = pm2['nombre_pieces_principales'].astype('category')
sns.set(rc={'figure.figsize':(40,30)})
sns.color_palette()
sns.catplot(x="nombre_pieces_principales", y="prix_m2", jitter=True, data=pm2, kind="strip", height=8, aspect=1.5, palette="Set2")
<seaborn.axisgrid.FacetGrid at 0x7fe8838d8790>
IV ] Comparaison avec 2021¶
Importation et nettoyage des données de 2021
df2021 = pd.read_csv('https://static.data.gouv.fr/resources/demandes-de-valeurs-foncieres/20230405-155828/valeursfoncieres-2021.txt', sep = '|')
df2021 = df2021.rename(columns=lambda x: x.replace(' ', '_').lower())
df2021 = df2021.drop(['identifiant_de_document',
'reference_document',
'1_articles_cgi',
'2_articles_cgi',
'3_articles_cgi',
'4_articles_cgi',
'5_articles_cgi',
'prefixe_de_section',
'no_volume',
'3eme_lot',
'4eme_lot',
'5eme_lot',
'identifiant_local',
'nature_culture_speciale',
],axis= 1)
# suppression des doubles
df2021 = df2021.drop_duplicates()
# suppression des ligne null
df2021 = df2021.dropna(how="all")
df2021 = df2021.drop_duplicates()
df2021['valeur_fonciere'] = df2021['valeur_fonciere'].str.replace(',', '.').astype('float')
df2021['surface_carrez_du_1er_lot'] = df2021['surface_carrez_du_1er_lot'].str.replace(',', '.').astype('float')
df2021['surface_carrez_du_2eme_lot'] = df2021['surface_carrez_du_2eme_lot'].str.replace(',', '.').astype('float')
df2021['surface_carrez_du_3eme_lot'] = df2021['surface_carrez_du_3eme_lot'].str.replace(',', '.').astype('float')
df2021['surface_carrez_du_4eme_lot'] = df2021['surface_carrez_du_4eme_lot'].str.replace(',', '.').astype('float')
df2021['surface_carrez_du_5eme_lot'] = df2021['surface_carrez_du_5eme_lot'].str.replace(',', '.').astype('float')
df2021.info()
df2021.head()
<class 'pandas.core.frame.DataFrame'> Int64Index: 4303715 entries, 0 to 4649208 Data columns (total 29 columns): # Column Dtype --- ------ ----- 0 no_disposition int64 1 date_mutation object 2 nature_mutation object 3 valeur_fonciere float64 4 no_voie float64 5 b/t/q object 6 type_de_voie object 7 code_voie object 8 voie object 9 code_postal float64 10 commune object 11 code_departement object 12 code_commune int64 13 section object 14 no_plan int64 15 1er_lot object 16 surface_carrez_du_1er_lot float64 17 2eme_lot object 18 surface_carrez_du_2eme_lot float64 19 surface_carrez_du_3eme_lot float64 20 surface_carrez_du_4eme_lot float64 21 surface_carrez_du_5eme_lot float64 22 nombre_de_lots int64 23 code_type_local float64 24 type_local object 25 surface_reelle_bati float64 26 nombre_pieces_principales float64 27 nature_culture object 28 surface_terrain float64 dtypes: float64(12), int64(4), object(13) memory usage: 985.0+ MB
| no_disposition | date_mutation | nature_mutation | valeur_fonciere | no_voie | b/t/q | type_de_voie | code_voie | voie | code_postal | ... | surface_carrez_du_3eme_lot | surface_carrez_du_4eme_lot | surface_carrez_du_5eme_lot | nombre_de_lots | code_type_local | type_local | surface_reelle_bati | nombre_pieces_principales | nature_culture | surface_terrain | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 05/01/2021 | Vente | 185000.0 | 5080.0 | NaN | CHE | 0471 | DE VOGELAS | 1370.0 | ... | NaN | NaN | NaN | 0 | 1.0 | Maison | 97.0 | 5.0 | S | 2410.0 |
| 1 | 1 | 05/01/2021 | Vente | 185000.0 | 5080.0 | NaN | CHE | 0471 | DE VOGELAS | 1370.0 | ... | NaN | NaN | NaN | 0 | 3.0 | Dépendance | 0.0 | 0.0 | S | 2410.0 |
| 2 | 1 | 06/01/2021 | Vente | 10.0 | NaN | NaN | NaN | B043 | ROUGEMONT | 1290.0 | ... | NaN | NaN | NaN | 0 | NaN | NaN | NaN | NaN | BT | 530.0 |
| 3 | 1 | 04/01/2021 | Vente | 204332.0 | 7.0 | NaN | ALL | 0276 | DES ECUREUILS | 1310.0 | ... | NaN | NaN | NaN | 0 | 1.0 | Maison | 88.0 | 4.0 | S | 866.0 |
| 4 | 1 | 06/01/2021 | Vente | 320000.0 | 87.0 | NaN | RTE | 0140 | DE CERTINES | 1250.0 | ... | NaN | NaN | NaN | 0 | 1.0 | Maison | 168.0 | 5.0 | S | 1426.0 |
5 rows × 29 columns
- Comparaison du prix moyen du mètre carré entre 2021 et 2022
pm2_22 = df[(df['nombre_de_lots']<6) & ((df['surface_carrez_du_1er_lot'] + df['surface_carrez_du_2eme_lot'] + df['surface_carrez_du_3eme_lot'] + df['surface_carrez_du_4eme_lot'] + df['surface_carrez_du_5eme_lot']) > 0)]
pm2_22['surface_totale'] = pm2_22['surface_carrez_du_1er_lot'] + pm2_22['surface_carrez_du_2eme_lot'] + pm2_22['surface_carrez_du_3eme_lot'] + pm2_22['surface_carrez_du_4eme_lot'] + pm2_22['surface_carrez_du_5eme_lot']
pm2_22['prix_m2'] = pm2_22['valeur_fonciere'] / pm2_22['surface_totale']
pm2_21 = df2021[(df2021['nombre_de_lots']<6) & ((df2021['surface_carrez_du_1er_lot'] + df2021['surface_carrez_du_2eme_lot'] + df2021['surface_carrez_du_3eme_lot'] + df2021['surface_carrez_du_4eme_lot'] + df2021['surface_carrez_du_5eme_lot']) > 0)]
pm2_21['surface_totale'] = pm2_21['surface_carrez_du_1er_lot'] + pm2_21['surface_carrez_du_2eme_lot'] + pm2_21['surface_carrez_du_3eme_lot'] + pm2_21['surface_carrez_du_4eme_lot'] + pm2_21['surface_carrez_du_5eme_lot']
pm2_21['prix_m2'] = pm2_21['valeur_fonciere'] / pm2_21['surface_totale']
fig = plt.figure(11,figsize = (10,5))
axis = fig.add_subplot(1, 1, 1)
axis.set_title('Comparaison du prix du mètre carré entre 2021 et 2022')
axis.set_xlabel("Année")
axis.set_ylabel("Prix")
gb1 = pm2_21['prix_m2'].mean()
gb2 = pm2_22['prix_m2'].mean()
com = ['2021','2022']
prix = [gb1,gb2]
axis.bar(com[:],prix[:])
plt.xticks(ticks=com,labels=prix,rotation=0)
fig.show()
On remarque que la valeur foncière moyenne est plus haute sur l'année 2022 que sur l'année 2021.
- Comparaison de la nature des mutations
mutation_type2021 = df2021['nature_mutation']
r2021 = Counter(mutation_type2021)
mutation_type2022 = df['nature_mutation']
r2022 = Counter(mutation_type2022)
mutation_df2021 = pd.DataFrame.from_dict(r2021, orient='index').sort_values(by=0)
mutation_df2021.columns = ['nature_mutation']
mutation_df2022 = pd.DataFrame.from_dict(r2022, orient='index').sort_values(by=0)
mutation_df2022.columns = ['nature_mutation']
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(32, 8))
mutation_df2021.plot.pie(y = 'nature_mutation',
colormap = 'Reds_r',
figsize = (16, 16),
fontsize = 9,
autopct = '%.2f',
legend = False,
title = 'Diagramme de distribution de la nature des mutations en 2021',
ax=ax1)
mutation_df2022.plot.pie(y = 'nature_mutation',
colormap = 'Reds_r',
figsize = (16, 16),
fontsize = 9,
autopct = '%.2f',
legend = False,
title = 'Diagramme de distribution de la nature des mutations 2022',
ax=ax2,
)
# Ajouter un cercle au centre pour faire un donut chart
mutation_df2021=plt.Circle( (0,0), 0.7, color='white')
mutation_df2022=plt.Circle( (0,0), 0.7, color='white')
plt.show()
On remarque qu'il n'y a presque pas de différence dans la répartition des natures de mutation entre l'année 2021 et 2022
On créé un nouveau dataframe rassemblant les donnée de 2021 et 2022
df['year'] = int(2022)
df2021['year'] = int(2021)
all_years = [ df, df2021]
data_years = pd.concat(all_years)
- Surface du terrain en fonction du département entre 2021 et 2022
fig = plt.figure(4,figsize = (35,10))
axis = fig.add_subplot(1, 1, 1)
axis.set_title('Surface du terrain en fonction du département entre 2021 et 2022')
axis.set_xlabel("Département")
axis.set_ylabel("Surface du terrain")
gb = data_years.loc[data_years["code_departement"].notna(),("surface_terrain","code_departement","year")]
ax = sns.barplot(x=gb["code_departement"].astype(str), y=gb["surface_terrain"], hue="year", data = gb)
plt.xticks(rotation=90)
fig.show()
- Relation entre la commune et la valeur foncière en fonction de la commune
sns.set_theme(style="ticks", palette="pastel")
df_ve = data_years[data_years['nature_mutation']=='Vente'].sort_values(by='valeur_fonciere', ascending=False)
se_vente_commune = df_ve.commune.value_counts()
plt.figure(figsize=(10,5))
df_best_city = df_ve[df_ve['commune'].isin(se_vente_commune.head(10).index)]
df_best_city = df_best_city[df_best_city['valeur_fonciere'] < df_best_city['valeur_fonciere'].quantile(.95)]
df_best_city = df_best_city[df_best_city['valeur_fonciere'] > df_best_city['valeur_fonciere'].quantile(.05)]
order=df_best_city['valeur_fonciere'].groupby(df_best_city.commune).median().sort_values(ascending=False)
plt.figure(figsize=(20,10))
ax = sns.boxplot(x=df_best_city.commune, y=df_best_city['valeur_fonciere'], hue=df_best_city['year'], order=order.index, palette=["m", "g"],)
plt.legend(loc = 'upper right')
ax.set_title('Relation entre la commune et la valeur foncière')
ax.set_xlabel('Commune')
ax.set_ylabel('Valeur foncière')
Text(0, 0.5, 'Valeur foncière')
<Figure size 1500x750 with 0 Axes>
- Nombre de biens vendus par commune en 2022 et 2021
sns.set_style('whitegrid')
sns.set(rc={'figure.figsize':(18,5), 'figure.dpi': 150})
vente_ville = data_years.groupby(['commune','year']).size().sort_values(ascending=False).head(20).reset_index(name='nombre')
ax = sns.scatterplot(x='commune', y='nombre', hue='year', data=vente_ville, color='#119670', palette=["b", "r"], marker='o')
ax.set_title('Nombre de biens vendus par commune en 2022 et 2021')
ax.set_xlabel('Commune')
ax.set_ylabel('Nombre de biens')
Text(0, 0.5, 'Nombre de biens')
On remarque que les villes dans lequel le plus de transaction ont été fait sont différente entre 2021 et 2022
*Licence :* Licence Ouverte / Open Licence version 2.0